package sg.edu.nus.iss.jass.controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.swing.JComponent;
import javax.swing.JOptionPane;

import sg.edu.nus.iss.jass.dao.CompanyDAO;
import sg.edu.nus.iss.jass.dao.JobAdvertDAO;
import sg.edu.nus.iss.jass.dao.SkillDAO;
import sg.edu.nus.iss.jass.gui.AddJobAdvertPanel;
import sg.edu.nus.iss.jass.gui.EditJobAdvertPanel;
import sg.edu.nus.iss.jass.gui.SearchJobAdvertPanel;
import sg.edu.nus.iss.jass.gui.ViewJobAdvertPanel;
import sg.edu.nus.iss.jass.model.CompanyDTO;
import sg.edu.nus.iss.jass.model.JobAdvertDTO;
import sg.edu.nus.iss.jass.model.SkillDTO;
/**
 * This class object co-ordinates the JobAdvert Maintenance related functions by the Advertiser. It receives request to perform the following functions:
 * <br/> - Add JobAdvert
 * <br/> - View JobAdvert
 * <br/> - Edit JobAdvert
 * <br/> - Delete JobAdvert
 * <br/> - Withdraw JobAdvert
 * <br/> - Search JobAdvert
 * 
 * <p>It manages the interaction between the JobAdvert Maintenance screens and the Data Access Object(DAO).</p>
 * 
 * @author SE19 Team 1
 * @version 1.0
 */	
public class JobAdvertController implements ActionListener {
	
	MainMenuController mainMenuController;
	AddJobAdvertPanel addJobAdvertPanel;
	EditJobAdvertPanel editJobAdvertPanel;
	ViewJobAdvertPanel viewJobAdvertPanel;
	SearchJobAdvertPanel searchJobAdvertPanel;
	
	/**
	 * This operation is the default constructor of JobAdvertController.&nbsp;The parameters of the operation 
	 * will define the initial value for the attribute of the controller.
	 * 
	 * @param mainMenuController A reference to the main menu controller.
	 */
	public JobAdvertController(MainMenuController mainMenuController) {
		this.mainMenuController = mainMenuController;
	}
	
	/**
	 * This operation is implementing the ActionListener interface.&nbsp;It will listen to the event of the button 
	 * and invokes the respective operation to complete a request.
	 * 
	 * @param e A semantic event which indicates that a component-defined action occured.
	 */
	public void actionPerformed(ActionEvent e) {
		String button = ((JComponent)e.getSource()).getName();
		
		//Add Job Advertisement Buttons
		if(AddJobAdvertPanel.BTN_ADD_JOBADVERT.equals(button)) {
			JobAdvertDTO jobadvertDTO = addJobAdvertPanel.getFormData();
			if(jobadvertDTO != null) {
				addJobAdvert(jobadvertDTO);
				addJobAdvertPanel.displayAddSuccessMsg();
				initViewJobAdvertScreen(jobadvertDTO.getId());
			}
		}
		else if(AddJobAdvertPanel.BTN_CLEAR.equals(button)) {
			addJobAdvertPanel.clearFormData();
		}
		
		//View Job Advertisement Buttons
		else if(ViewJobAdvertPanel.BTN_EDIT_JOBADVERT.equals(button)) {
			initEditJobAdvertScreen(viewJobAdvertPanel.getJobAdvertId());
		}
		else if(ViewJobAdvertPanel.BTN_WITHDRAW_JOBADVERT.equals(button)) {
			withdrawJobAdvert(viewJobAdvertPanel.getJobAdvertId());
			
			viewJobAdvertPanel.displayWithdrawSuccessMsg();
			initViewJobAdvertScreen(viewJobAdvertPanel.getJobAdvertId());
		}
		else if(ViewJobAdvertPanel.BTN_DELETE_JOBADVERT.equals(button)) {
			deleteJobAdvert(viewJobAdvertPanel.getJobAdvertId());
			
			viewJobAdvertPanel.displayDeleteSuccessMsg();
			mainMenuController.displayMainMenu();
		}
		
		//Edit Job Advertisement Buttons
		else if(EditJobAdvertPanel.BTN_UPDATE_JOBADVERT.equals(button)) {
			JobAdvertDTO jobadvertDTO = editJobAdvertPanel.getFormData();
			if(jobadvertDTO != null) {
				updateJobAdvert(jobadvertDTO);
				editJobAdvertPanel.displayUpdateSuccessMsg();
			}
		}
		
		//Back to search screen from view or edit screen 
		else if(EditJobAdvertPanel.BTN_BACK_TO_SEARCH.equals(button) || ViewJobAdvertPanel.BTN_BACK_TO_SEARCH.equals(button)) {
			if(searchJobAdvertPanel != null) {
				mainMenuController.switchPage(searchJobAdvertPanel);
			}
			else {
				initSearchJobAdvertScreen(mainMenuController.getCurrentUser().getUserId());
			}
		}
		
		//Search Job Advertisement Buttons
		else if(SearchJobAdvertPanel.BTN_SEARCH_JOBADVERT.equals(button)) {
			searchJobAdvert(searchJobAdvertPanel.getFormData());
		}
		else if(SearchJobAdvertPanel.BTN_VIEW_JOBADVERT.equals(button)) {
			initViewJobAdvertScreen(searchJobAdvertPanel.getSelectedJobAdvertId());
		}
	}
	
	/**
	 * This operation initiates when the user(Advertiser) selects on add new JobAdvert on the Main
	 * Menu Screen.&nbsp;It will perform the following steps:<br/>
	 * 		<br/>1) Retrieve the skill and company data.&nbsp;
	 * 		<br/>2) Forward the completed request to display Add JobAdvert Screen.&nbsp;
	 * 
	 * @param id An unique Id of the current logon user.
	 */
	public void initAddJobAdvertScreen(String id) {
		SkillDAO skillDAO = new SkillDAO();
		CompanyDAO companyDAO = new CompanyDAO();
		
		List<SkillDTO> skills = skillDAO.getSkillList();
		List<CompanyDTO> companies = companyDAO.getCompanyList();
		
		addJobAdvertPanel = new AddJobAdvertPanel(id, skills, companies);
		addJobAdvertPanel.addComponentActionListener(this);
		mainMenuController.switchPage(addJobAdvertPanel);
	}
	
	/**
	 * This operation initiates when the user(Advertiser) selects on Search JobAdvert on the
	 * Main Menu Screen.&nbsp;It will perform the following steps:<br/>
	 * 		<br/>1) Retrieve the skill and company data.&nbsp;
	 * 		<br/>2) Retrieve the all JobAdvert detail based on search criteria from the response data source (i.e.&nbsp;associated JobAdvert detail from the JobAdvert data source (i.e.&nbsp;jobadvert.properties).&nbsp;
	 * 		<br/>3) Forward the completed request to display Search JobAdvert Screen.&nbsp;
	 * 
	 * @param id An unique Id of the current logon user.
	 */
	public void initSearchJobAdvertScreen(String id) {
		SkillDAO skillDAO = new SkillDAO();
		CompanyDAO companyDAO = new CompanyDAO();
		
		List<SkillDTO> skills = skillDAO.getSkillList();
		List<CompanyDTO> companies = companyDAO.getCompanyList();
		
		searchJobAdvertPanel = new SearchJobAdvertPanel(skills, companies);
		searchJobAdvertPanel.addComponentActionListener(this);
		mainMenuController.switchPage(searchJobAdvertPanel);
	}
	
	/**
	 * This operation initiates when the user(Advertiser) selects on View JobAdvert on the
	 * Search JobAdvert Screen.&nbsp;It will perform the following steps:<br/>
	 * 		<br/>1) Retrieve the skill and company data.&nbsp;
	 * 		<br/>2) Retrieve the JobAdvert detail from the response data source (i.e.&nbsp;associated JobAdvert detail from the JobAdvert data source (i.e.&nbsp;jobadvert.properties).&nbsp;
	 * 		<br/>3) Forward the completed request to display View JobAdvert Screen.&nbsp;
	 * 
	 * @param id An unique Id that represents the selected JobAdvert.
	 */
	public void initViewJobAdvertScreen(String id) {
		if(id != null && id.length() > 0){
			JobAdvertDAO jobAdvertDAO = new JobAdvertDAO();
			JobAdvertDTO jobAdvertDTO = jobAdvertDAO.getJobAdvert(id);
			
			SkillDAO skillDAO = new SkillDAO();
			jobAdvertDTO.setSkills(constructSkills(skillDAO, jobAdvertDTO.getSkillsStr()));
			
			CompanyDAO companyDAO = new CompanyDAO();
			jobAdvertDTO.setCompany((CompanyDTO)companyDAO.getObject(jobAdvertDTO.getCompanyId()));
			
			viewJobAdvertPanel = new ViewJobAdvertPanel(jobAdvertDTO);
			viewJobAdvertPanel.addComponentActionListener(this);
			mainMenuController.switchPage(viewJobAdvertPanel);
		} else {
			JOptionPane.showMessageDialog(searchJobAdvertPanel, "Please Select Job Advert", "Search Job Advert", JOptionPane.INFORMATION_MESSAGE);
		}
	}
	
	/**
	 * This operation initiates when the user(Advertiser) selects on edit JobAdvert on the
	 * View JobAdvert Screen.&nbsp;It will perform the following steps:<br/>
	 * 		<br/>1) Retrieve the skill and company data.&nbsp;
	 * 		<br/>2) Retrieve the JobAdvert detail from the response data source (i.e.&nbsp;associated JobAdvert detail from the JobAdvert data source (i.e.&nbsp;jobadvert.properties).&nbsp;
	 * 		<br/>3) Forward the completed request to display Edit JobAdvert Screen.&nbsp;
	 * 
	 * @param id An unique Id that represents the selected JobAdvert.
	 */
	public void initEditJobAdvertScreen(String id) {
		if(id != null && id.length() > 0) {
			SkillDAO skillDAO = new SkillDAO();
			CompanyDAO companyDAO = new CompanyDAO();
			JobAdvertDAO jobAdvertDAO = new JobAdvertDAO();
			
			List<SkillDTO> skills = skillDAO.getSkillList();
			List<CompanyDTO> companies = companyDAO.getCompanyList();
			
			// To retrieve the latest record for editing.
			JobAdvertDTO jobAdvertDTO = (JobAdvertDTO)jobAdvertDAO.getObject(id);
			jobAdvertDTO.setSkills(constructSkills(skillDAO, jobAdvertDTO.getSkillsStr()));
			jobAdvertDTO.setCompany((CompanyDTO)companyDAO.getObject(jobAdvertDTO.getCompanyId()));
			
			editJobAdvertPanel = new EditJobAdvertPanel(jobAdvertDTO, skills, companies);
			editJobAdvertPanel.addComponentActionListener(this);
			mainMenuController.switchPage(editJobAdvertPanel);
		}
	}
	
	/**
	 * This operation inserts new JobAdvert into the JobAdvert data source (i.e.&nbsp;jobadvert.properties).&nbsp; 
	 * It will perform the following steps:<br/>
	 * 		<br/>1) Retrieve total records in data source.&nbsp;
	 * 		<br/>2) Generate reference code based on the number of records. &nbsp;
	 * 		<br/>3) Insert skill, company, user(Adviser) and current date to JobAdvert data source.&nbsp;
	 * 		
	 * 
	 * @param jobAdvertDTO A JobAdvertDTO that stores the new job advertisement details.
	 */
	public void addJobAdvert(JobAdvertDTO jobAdvertDTO){
		if(jobAdvertDTO != null) {
			JobAdvertDAO jobAdvertDAO = new JobAdvertDAO();
			
			// 1. Populate the necessary new parameter into the JobAdvertDTO.
			int nextSeqId = jobAdvertDAO.getTotal() + 1;
			jobAdvertDTO.setId(nextSeqId + "");
			jobAdvertDTO.setReferenceCode(JobAdvertDAO.generateReferenceCode(nextSeqId));
			jobAdvertDTO.setSkillsStr(constructSkillsStr(jobAdvertDTO.getSkills()));
			jobAdvertDTO.setCreateDate(new Date());
			
			// 2. Not to write Skills list object and company object into the properties file.
			jobAdvertDTO.setSkills(null);
			jobAdvertDTO.setCompany(null);
			
			// 3. Write New Job Advert details into the properties file.
			jobAdvertDAO.addJobAdvert(jobAdvertDTO);
		}
	}
	
	/**
	 * This operation updates JobAdvert into the JobAdvert data source (i.e.&nbsp;jobadvert.properties).&nbsp; 
	 * It will perform the following steps:<br/>
	 * 		<br/>1) Retrieve JobAdvert information.&nbsp;
	 * 		<br/>2) User makes changes whatever needed.&nbsp;
	 * 		<br/>3) Update skill, company, user(Adviser) and current date to JobAdvert data source.&nbsp;
	 * 		
	 * 
	 * @param jobAdvertDTO A JobAdvertDTO that stores the updated job advertisement details.
	 */
	public void updateJobAdvert (JobAdvertDTO jobAdvertDTO) {
		if(jobAdvertDTO != null) {
			JobAdvertDAO jobAdvertDAO = new JobAdvertDAO();
			
			// 1. Re-construct skills before writing to properties file.
			jobAdvertDTO.setSkillsStr(constructSkillsStr(jobAdvertDTO.getSkills()));
			
			// 2. Not to write skills list object and company object into the properties file.
			jobAdvertDTO.setSkills(null);
			jobAdvertDTO.setCompany(null);
			
			// 3. Write the updated Job Advert details into the properties file.
			jobAdvertDAO.updateJobAdvert(jobAdvertDTO);
		}
	}
	
	/**
	 * This operation changes the status of JobAdvert into deleted in the JobAdvert data source (i.e.&nbsp;jobadvert.properties).&nbsp; 
	 * It will perform the following steps:<br/>
	 * 		<br/>1) Retrieve JobAdvert information.&nbsp;
	 * 		<br/>2) User click delete JobAdvert button.&nbsp;
	 * 		<br/>3) Update status to deleted in JobAdvert data source.&nbsp;
	 * 		
	 * 
	 * @param id An unique Id of the job advertisement to be deleted.
	 */
	public void deleteJobAdvert (String id) {
		if(id != null && id.length() > 0) {
			JobAdvertDAO jobAdvertDAO = new JobAdvertDAO();
			JobAdvertDTO jobAdvertDTO = jobAdvertDAO.getJobAdvert(id);
			jobAdvertDTO.setStatus(2);
			jobAdvertDAO.updateJobAdvert(jobAdvertDTO);
		}
	}
	
	/**
	 * This operation changes the status of JobAdvert into withdraw in the JobAdvert data source (i.e.&nbsp;jobadvert.properties).&nbsp; 
	 * It will perform the following steps:<br/>
	 * 		<br/>1) Retrieve JobAdvert information.&nbsp;
	 * 		<br/>2) User click withdraw JobAdvert button.&nbsp;
	 * 		
	 * 	
	 * 
	 * @param id An unique Id of the job advertisement to be withdraw.
	 */
	public void withdrawJobAdvert (String id) {
		if(id != null && id.length() > 0) {
			JobAdvertDAO jobAdvertDAO = new JobAdvertDAO();
			JobAdvertDTO jobAdvertDTO = jobAdvertDAO.getJobAdvert(id);
			jobAdvertDTO.setStatus(3);
			jobAdvertDAO.updateJobAdvert(jobAdvertDTO);
		}
	}
	
	/**
	 * This operation retrieves filtered search JobAdvert based on the search criteria from the JobAdvert data source (i.e.&nbsp;jobadvert.properties).&nbsp; 
	 * It will perform the following steps:<br/>
	 * 		<br/>1) If there is no search criteria, it will clear search JobAdvert panel.&nbsp;
	 * 		<br/>2) If there is no search result, it will display no result message.&nbsp;
	 * 		<br/>3) If there is search result, it will display the result.&nbsp;
	 * 		
	 * @param searchCriteriaMap A HashMap that contains the search criteria for job advertisement.
	 */
	public void searchJobAdvert(HashMap<String, Object> searchCriteriaMap) {
		if(searchCriteriaMap == null){
			searchJobAdvertPanel.clearResultPanel();
		}
		else {
			JobAdvertDAO jobAdvertDAO = new JobAdvertDAO();
			List<JobAdvertDTO> filteredJobAdvertList = filterSearchResultJobAdvert(searchCriteriaMap, jobAdvertDAO.getJobAdvertList());
			
			if(filteredJobAdvertList.isEmpty()) {
				searchJobAdvertPanel.displayNoResultError();
			} else {
				searchJobAdvertPanel.displayResultPanel(filteredJobAdvertList);
			}
		}
	}
	
	/**
	 * This operation retrieves filtered list of JobAdvert.&nbsp;  
	 * It will perform the following steps:<br/>
	 * 		<br/>1) Retrieve the skill, company data and CurrentUser.&nbsp;
	 * 		<br/>2) Match the keywords with title and description.&nbsp;
	 * 		<br/>3) Match the skills with skills information.&nbsp;
	 * 		<br/>4) Match the company with company information.&nbsp;
	 * 		<br/>5) Match the minimum salary with minimum salary.&nbsp;
	 * 		<br/>6) Match the start date with JobAdvert start date.&nbsp;
	 * 		<br/>7) Match the create date with JobAdvert create date.&nbsp;
	 * 		<br/>8) If there is any data based on the search criteria, it will forward to display result panel.&nbsp;		
	 * 		<br/>9) If there is nothing matched, it will display no panel.&nbsp;
	 * 
	 * @param searchCriteriaMap A HashMap that contains the search criteria for job advertisement.
	 * @param fullList A list of job advertisement that will returned from the search.
	 * @return A list of matching job advertisement.
	 */
	public List<JobAdvertDTO> filterSearchResultJobAdvert(HashMap<String, Object> searchCriteriaMap, List<JobAdvertDTO> fullList) {
		List<JobAdvertDTO> filteredJobAdvertList = new ArrayList<JobAdvertDTO>();
		
		for (JobAdvertDTO jobAdvert : fullList){
			boolean match = true;
			if(!jobAdvert.getAdvertiser().equals(mainMenuController.getCurrentUser().getUserId())){
				match = false;
			}
			
			//Keywords
			if(searchCriteriaMap.get("Keywords") != null) {
				String title = jobAdvert.getJobTitle().toLowerCase();
				String desc = jobAdvert.getJobDescription().toLowerCase();
				String[] searchTerms = ((String) searchCriteriaMap.get("Keywords")).toLowerCase().split(" ");
				
				boolean keywordMatch = true;
				for(String searchTerm : searchTerms) {
					if(title.indexOf(searchTerm) == -1 && desc.indexOf(searchTerm) == -1) {
						keywordMatch = false;
					}
				}
				
				if(!keywordMatch) {
					match = false;
				}
			}
			
			//Skills
			if(searchCriteriaMap.get("Skills") != null) {
				SkillDAO skillDAO = new SkillDAO();
				List<SkillDTO> skills = constructSkills(skillDAO, jobAdvert.getSkillsStr());
				List<SkillDTO> searchTerms = (List<SkillDTO>) searchCriteriaMap.get("Skills");
				
				for(SkillDTO searchTerm : searchTerms){
					boolean skillMatch = false;
					for(SkillDTO skill : skills){
						if(skill.getCode().equals(searchTerm.getCode()) && skill.getProficiencyLevel().equals(searchTerm.getProficiencyLevel())) {
							skillMatch = true;
						}
					}

					if(!skillMatch) {
						match = false;
					}
				}
				
			}
			
			//Location
			if(searchCriteriaMap.get("Location") != null) {
				String location = jobAdvert.getLocation().toLowerCase();
				String searchTerm = ((String) searchCriteriaMap.get("Location")).toLowerCase();
				
				if(location.indexOf(searchTerm) == -1) {
					match = false;
				}
			}
			
			//Company
			if(searchCriteriaMap.get("Company") != null) {
				String companyId = jobAdvert.getCompanyId().toLowerCase();
				String searchTerm = ((String) searchCriteriaMap.get("Company")).toLowerCase();
				
				if(!companyId.equals(searchTerm)) {
					match = false;
				}
			}
			
			//Salary Range
			if(searchCriteriaMap.get("MinSalary") != null || searchCriteriaMap.get("MaxSalary") != null) {
				StringTokenizer st = new StringTokenizer(jobAdvert.getSalaryRange(), ",");
				int minSalary = Integer.parseInt(st.nextToken());
				int maxSalary = Integer.parseInt(st.nextToken());
				
				boolean checkMin = false, checkMax = false;
				int searchTermMin = 0, searchTermMax = 0;
				
				if(searchCriteriaMap.get("MinSalary") != null) {
					checkMin = true;
					searchTermMin = Integer.parseInt((String) searchCriteriaMap.get("MinSalary"));
				}
				if(searchCriteriaMap.get("MaxSalary") != null) {
					checkMax = true;
					searchTermMax = Integer.parseInt((String) searchCriteriaMap.get("MaxSalary"));
				}
				
				if((checkMin && maxSalary < searchTermMin) || (checkMax && minSalary > searchTermMax)) {
					match = false;
				}
			}
			
			//Start Date
			if(searchCriteriaMap.get("MinStartDate") != null || searchCriteriaMap.get("MaxStartDate") != null) {
				Date startDate = jobAdvert.getStartDate();
				
				boolean checkMin = false, checkMax = false;
				Date searchTermMin = null, searchTermMax = null;
				DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
				
				if(searchCriteriaMap.get("MinStartDate") != null) {
					checkMin = true;
					try {
						searchTermMin = df.parse((String) searchCriteriaMap.get("MinStartDate"));
					} catch(Exception ex) {
						
					}
				}
				if(searchCriteriaMap.get("MaxStartDate") != null) {
					checkMax = true;
					try {
						searchTermMax = df.parse((String) searchCriteriaMap.get("MaxStartDate"));
					} catch(Exception ex) {
						
					}
				}
				
				if((checkMin && startDate.before(searchTermMin)) || (checkMax && startDate.after(searchTermMax))) {
					match = false;
				}
			}
			
			//Create Date
			if(searchCriteriaMap.get("MinCreateDate") != null || searchCriteriaMap.get("MaxCreateDate") != null) {
				Date createDate = jobAdvert.getCreateDate();
				
				boolean checkMin = false, checkMax = false;
				Date searchTermMin = null, searchTermMax = null;
				DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
				
				if(searchCriteriaMap.get("MinCreateDate") != null) {
					checkMin = true;
					try {
						searchTermMin = df.parse((String) searchCriteriaMap.get("MinCreateDate"));
					} catch(Exception ex) {
						
					}
				}
				if(searchCriteriaMap.get("MaxCreateDate") != null) {
					checkMax = true;
					try {
						searchTermMax = df.parse((String) searchCriteriaMap.get("MaxCreateDate"));
					} catch(Exception ex) {
						
					}
				}
				
				if((checkMin && createDate.before(searchTermMin)) || (checkMax && createDate.after(searchTermMax))) {
					match = false;
				}
			}
			
			if(match && jobAdvert.getStatus().intValue() != 2) {
				filteredJobAdvertList.add(jobAdvert);
			}
		}
		
		return filteredJobAdvertList;
	}
	
	/**
	 * This operation generates string of skill list with comma separated.&nbsp; 
	 * 
	 * @param skillDAO The skill data source (i.e.&nbsp;skill.properties) 
	 * @param selectedSkillStr A list of skill selected for JobAdvert.
	 * @return A list of SkillDTO.
	 */
	private List<SkillDTO> constructSkills(SkillDAO skillDAO, String selectedSkillStr) {
		List<SkillDTO> skills = new ArrayList<SkillDTO>();
		StringTokenizer st = new StringTokenizer(selectedSkillStr, ",");
		
		while(st.hasMoreTokens()) {
			String tempStr = st.nextToken();
			StringTokenizer tempTokenizer = new StringTokenizer(tempStr, "|");
			
			SkillDTO skillDTO = (SkillDTO)skillDAO.getObject(tempTokenizer.nextToken());
			skillDTO.setProficiencyLevel(tempTokenizer.nextToken());
			skills.add(skillDTO);
		}		
		return skills;
	}
	
	/**
	 * This operation generates string of company list with comma separated.&nbsp;
	 * 
	 * @param selectedSkills A list of skill selected for JobAdvert.
	 * @return A concatenated string of the skillId and proficiency level.
	 */
	private String constructSkillsStr(List<SkillDTO> selectedSkills) {
		StringBuffer buffer = new StringBuffer();
		Iterator<SkillDTO> iter = selectedSkills.iterator();
		
		while(iter.hasNext()) {
			if(buffer.length() != 0)
				buffer.append(",");
			
			SkillDTO temp = iter.next();
			buffer.append(temp.getId() + "|");
			buffer.append(temp.getProficiencyLevel());
		}
		return buffer.toString();
	}
}
